use chrono::Local;
use tera::Context;
use serde_json::json;
use actix_files::NamedFile;
use actix_session::Session;
use actix_web::{
    get, post, Error, Result,
    Responder, web::{Query, Form},
    http::header::{ContentDisposition, DispositionType,DispositionParam}
};
use simple_excel_writer::{Workbook, Column, Row, row};
use crate::rules::Vo;
use crate::users::{status, rewards, educations};
use crate::util::{ctx, redirect, to_json_obj, to_json_list};
use crate::system::dao as systemDao;
use crate::users::dao as userDao;

// 跳转到档案管理菜单页
#[get("/userList.html")]
pub async fn user_list(session: Session) -> impl Responder {
    let mut context = Context::new();
    context.insert("status", &status());
    
    render!("users/userList.html", &ctx(context, &session))
}

// 查询人员信息
#[get("/userData.html")]
pub async fn user_data(data: Query<Vo>) -> Result<impl Responder> {
    let vo = data.into_inner();
    let cols = "id,name,username,passwords,gender,department,birthday,identity,telephone,education,hiredate,leavedate,statu,job";
    let count = userDao::user_count(&vo);
    let list = userDao::user_list(&cols, &vo);
    
    return Ok(to_json_list(map!{"code"=>json!("20"), "count"=>json!(&count), "list"=>json!(&list)}));
}

// 编辑人员信息
#[get("/editUser.html")]
pub async fn edit_user(session: Session, data: Query<Vo>) -> impl Responder {
    let mut context = Context::new();
    if data.not_blank("id") {
        let id = data.long("id");
        let cols = "id,name,num,username,passwords,gender,deptId,department,
                    birthday,identity,telephone,brand,team,education,graduationDate,school,
                    address,basicWage,insurance,hiredate,leavedate,statu,job";
        context.insert("bo", &(userDao::user_info(&cols, &id)));
        context.insert("attach", &(systemDao::get_attachment("path", &id, "users")));
    }
    context.insert("status", &status());
    context.insert("educations", &educations());
    context.insert("jobs", &(systemDao::get_dictionary("人事职务")));
    context.insert("depts", &(systemDao::department_list("id,name", &Vo{data: map!{}})));
    
    render!("users/editUser.html", &ctx(context, &session))
}

// 验证用户名是否已被注册
#[get("/validateUser.html")]
pub async fn validate_user(data: Query<Vo>) -> impl Responder {
    let vo = userDao::get_user("id", &data.str("username"), "");
    if vo.not_blank("id") && vo.str("id") != data.str("id") {
        return to_json_obj(map!{"code"=>"50"});
    }
    
    return to_json_obj(map!{"code"=>"20"});
}

// 保存人员信息
#[post("/saveUser.html")]
pub async fn save_user(data: Form<Vo>) -> impl Responder {
    let vo = data.into_inner();
    let id = userDao::save_users(&vo);
    if vo.not_blank("photoName") {
        systemDao::save_attachment(&id, vo.str("photoName"));
    }

    redirect("../users/userList.html")
}

// 查询职工奖惩记录
#[get("/usersRewardList.html")]
pub async fn users_reward_data(data: Query<Vo>) -> impl Responder {
    let vo = data.into_inner();
    let cols = "id,types,reward,rewardDate,money";
    let list = userDao::user_reward_list(&cols, &vo);
    
    return to_json_list(map!{"code"=>json!("20"), "count"=>json!(&list.len()), "list"=>json!(&list)});
}

// 编辑职工奖惩记录
#[get("/editUsersReward.html")]
pub async fn edit_user_reward(data: Query<Vo>) -> impl Responder {
    let mut context = Context::new();
    if data.blank("id") {
        context.insert("userId", &data.long("userId"));
    } else {
        let id = data.long("id");
        let cols = "id,userId,types,reward,money,leaveDays,rewardDate";
        context.insert("bo", &(userDao::user_reward_info(&cols, &id)));
    }
    context.insert("rewards", &rewards());
    context.insert("ctx", &crate::CONTEXT_PATH);
    
    render!("users/editUsersReward.html", &context)
}

// 保存职工奖惩记录
#[post("/saveUsersReward.html")]
pub async fn save_user_reward(data: Form<Vo>) -> impl Responder {
    userDao::save_user_reward(&data);

    to_json_obj(map!{"code"=>"20"})
}

// 权限配置列表
#[get("/authorization.html")]
pub async fn authorization(session: Session, data: Query<Vo>) -> impl Responder {
    let user_id = data.long("id");
    let menu_list = serde_json::to_string(&systemDao::user_menus(user_id)).unwrap();
    let mut context = Context::new();
    context.insert("id", &user_id);
    context.insert("menus", &(systemDao::menu_list()));
    context.insert("menuList", &menu_list);
    
    render!("users/authorization.html", &ctx(context, &session))
}

// 保存授权
#[post("/ajaxAuthorization.html")]
pub async fn ajax_authorization(data: Form<Vo>) -> Result<impl Responder> {
    systemDao::save_user_menus(&data);

    Ok(to_json_obj(map! {"code"=>"20"}))
}

// 打印人员列表
#[get("/printUser.html")]
pub async fn print_user(session: Session) -> impl Responder {
    let mut context = Context::new();
    context.insert("status", &status());
    
    render!("users/printUser.html", &ctx(context, &session))
}

// 导出人员列表
#[post("/exportUser.html")]
pub async fn export_user(session: Session, data: Form<Vo>) ->  Result<NamedFile, Error> {
    let user_id = session.get::<u32>("userId")?.unwrap();
    let filename = format!("/tmp/{}_{}.xlsx", user_id, Local::now().timestamp()) ;
    let mut wb = Workbook::create(&filename);
    let mut sheet = wb.create_sheet("列表详情");
    for _ in 0..16 {
        sheet.add_column(Column{width: 24.0});
    }

    wb.write_sheet(&mut sheet, |sheet_writer| {
        let sw = sheet_writer;
        let cols = "name,username,passwords,gender,department,birthday,identity,telephone,education,hiredate,leavedate,statu,job";
        let list = userDao::user_list(&cols, &data);
        sw.append_row(row!["序号","部门","职务","姓名","性别","出生年月","身份证号","联系方式","文化程度","用户名","密码","入职时间","离职时间","销售业绩","业绩排名","工资总额","人员状态"])?;
        for (num, vo) in list.iter().enumerate() {
            let mut row = Row::new();
            row.add_cell((num+1).to_string());
            row.add_cell(vo.str("department"));
            row.add_cell(vo.str("job"));
            row.add_cell(vo.str("name"));
            row.add_cell(vo.str("gender"));
            row.add_cell(vo.str("birthday"));
            row.add_cell(vo.str("identity"));
            row.add_cell(vo.str("telephone"));
            row.add_cell(vo.str("education"));
            row.add_cell(vo.str("username"));
            row.add_cell(vo.str("passwords"));
            row.add_cell(vo.str("hiredate"));
            row.add_cell(vo.str("leavedate"));
            row.add_empty_cells(3);
            row.add_cell(vo.str("statu"));
            let _ = sw.append_row(row);
        }
        
        Ok(())
    })?;
    wb.close()?;
   
    let file = NamedFile::open(&filename)?;
    Ok(file
        .use_last_modified(true)
        .set_content_type("application/vnd.ms-excel;charset=utf-8".parse().unwrap())
        .set_content_disposition(ContentDisposition {
            disposition: DispositionType::Attachment,
            parameters: vec![DispositionParam::Filename(String::from("人员列表.xlsx"))],
        }))
}
